package sk.gtug.pivoplus.malepivo.widget;

import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import sk.gtug.pivoplus.malepivo.R;
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Handler;
import android.text.Editable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.ImageButton;
import android.widget.LinearLayout;

/**
 * Custom compound control for searching address.
 * @author biegleux
 *
 */
public class AddressSearchView extends LinearLayout implements View.OnKeyListener,
	AdapterView.OnItemClickListener, View.OnClickListener {

	private AutoCompleteTextView mAddressSearchView;
	private ImageButton mSearchButton;
	private List<Address> mAddresses = null;
	private AddressSearchListener mListener;
	private Address mAddress;
	private Address mLastAddress;

	public AddressSearchView(Context context) {
		this(context, null);
	}

	public AddressSearchView(Context context, AttributeSet attrs) {
		super(context, attrs);
		LayoutInflater inflater = LayoutInflater.from(context);
		inflater.inflate(R.layout.address_search_view, this, true);
		setOrientation(HORIZONTAL);
		setFocusableInTouchMode(true);

		mAddressSearchView = (AutoCompleteTextView) findViewById(R.id.search_field);
		mSearchButton = (ImageButton) findViewById(R.id.search_button);

		mAddressSearchView.setOnKeyListener(this);
		mAddressSearchView.setOnItemClickListener(this);
		mAddressSearchView.setOnClickListener(this);

		mSearchButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				String address = mAddressSearchView.getText().toString().trim();
				performAddressSearch(address);
			}
		});
	}

	@Override
	public boolean onKey(View v, int keyCode, KeyEvent event) {
		if (event.getAction() == KeyEvent.ACTION_UP && (keyCode == KeyEvent.KEYCODE_ENTER
				|| keyCode == KeyEvent.KEYCODE_DPAD_CENTER)) {
			String address = mAddressSearchView.getText().toString().trim();
			performAddressSearch(address);
			
		}
		return false;
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		Address address = (Address) parent.getItemAtPosition(position);
		mAddressSearchView.setText(AddressAdapter.addrToString(address));
		if (mListener != null) {
			mListener.onAddressSearchResult(address);
		}
		//TODO trackball down vyvola dropdown znovu
	}

	@Override
	public void onClick(View v) {
		if (!TextUtils.isEmpty(mAddressSearchView.getText())) {
			mAddressSearchView.selectAll();
		}
	}

	private class AddressComparator implements Comparator<Address> {
		@Override
		public int compare(Address address1, Address address2) {
			float results[] = new float[1];
			float distance1, distance2;
			Location.distanceBetween(address1.getLatitude(), address1.getLongitude(),
					mLastAddress.getLatitude(), mLastAddress.getLongitude(), results);
			distance1 = results[0];
			Location.distanceBetween(address2.getLatitude(), address2.getLongitude(),
					mLastAddress.getLatitude(), mLastAddress.getLongitude(), results);
			distance2 = results[0];
			return (distance1 < distance2 ? -1 : (distance1 > distance2 ? 1 : 0));
		}
	}

	private void performAddressSearch(String locationName) {
		if (TextUtils.isEmpty(locationName)) {
			return;
		}

		if (mListener != null) {
			mListener.onAddressSearchBegin();
		}
/*
		if (mLastAddress != null) {
			if (!TextUtils.isEmpty(mLastAddress.getSubAdminArea())) {
				locationName += ", " + mLastAddress.getSubAdminArea();
			} else if (!TextUtils.isEmpty(mLastAddress.getAdminArea())) {
				locationName += ", " + mLastAddress.getAdminArea();
			}
			if (!TextUtils.isEmpty(mLastAddress.getCountryName())) {
				locationName += ", " + mLastAddress.getCountryName();
			}
		}
*/
		final String locationDesc = locationName;
		final Handler handler = new Handler();
		final int maxResults = 5;

		new Thread() {
			public void run() {
				try {
					mAddress = null;
					// neskor moze podla user prefs
					Geocoder geocoder = new Geocoder(getContext(), Locale.getDefault());
					mAddresses = geocoder.getFromLocationName(locationDesc, maxResults);
					handler.post(new Runnable() {
						@Override
						public void run() {
							if (mListener != null) {
								mListener.onAddressSearchEnd();
							}
							// remove addresses with no location specified
							if (mAddresses != null && !mAddresses.isEmpty()) {
								for (Iterator<Address> iter = mAddresses.iterator(); iter.hasNext();) {
									Address address = iter.next();
									if (!address.hasLatitude() || !address.hasLongitude()) {
										iter.remove();
									}
								}
							}
							if (mAddresses == null || mAddresses.isEmpty()) {
								mAddress = null;
								if (mListener != null) {
									mListener.onAddressSearchResult(mAddress);
								}
							} else if (mAddresses.size() == 1) {
								mAddress = mAddresses.get(0);
								if (mListener != null) {
									mListener.onAddressSearchResult(mAddress);
								}
							} else {
								if (mLastAddress != null & mLastAddress.hasLatitude()
										&& mLastAddress.hasLongitude()) {
									Collections.sort(mAddresses, new AddressComparator());
								}
								// we got more results, let the user decide which to use
								AddressAdapter addressesAdapter = new AddressAdapter(
										getContext(), R.layout.dropdown_item, mAddresses);
								mAddressSearchView.setAdapter(addressesAdapter);
								mAddressSearchView.showDropDown();
							}
						}
					});					
				} catch (IOException e) {
					handler.post(new Runnable() {
						@Override
						public void run() {
							if (mListener != null) {
								mListener.onAddressSearchEnd();
								mListener.onAddressSearchResult(null);
							}							
						}
					});
					e.printStackTrace();
				}
			}
		}.start();
	}

	public void hideSoftKeyboard() {
		InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
				Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(mAddressSearchView.getWindowToken(), 0);
	}

	public void showSoftKeyboard() {
		InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
				Context.INPUT_METHOD_SERVICE);
		imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
		mAddressSearchView.requestFocus();
	}

	public Editable getText() {
		return mAddressSearchView.getText();
	}

	public void setLastLocation(Address address) {
		mLastAddress = address;
	}

	public void setAddressSearchListener(AddressSearchListener listener) {
		mListener = listener;
	}

	public AddressSearchListener getAddressSearchListener() {
		return mListener;
	}

	public static interface AddressSearchListener {

		void onAddressSearchBegin();

		void onAddressSearchEnd();

		void onAddressSearchResult(Address address);
	}
}
